#ifndef STORAGE_LEVELDB_UTIL_CODING_H_
#define STORAGE_LEVELDB_UTIL_CODING_H_

#include <cstdint>
#include <cstring>
#include <string>

#include "leveldb/slice.h"
#include "port/port.h"

namespace leveldb {

// Standard Put... routines append to a string
// 把value编码后，放到dst字符串后面
void PutFixed32(std::string *dst, uint32_t value);
void PutFixed64(std::string *dst, uint64_t value);
void PutVarint32(std::string *dst, uint32_t value);
void PutVarint64(std::string *dst, uint64_t value);
// 把slice的长度，data一起编码，放到dst里面去
void PutLengthPrefixedSlice(std::string *dst, const Slice &value);

// Standard Get... routines parse a value from the beginning of a Slice
// and advance the slice past the parsed value.

// 意思大概是len+key会在一起存储，都在slice的data里面，这个函数可以把他们分离出来，使得input剥离len，只有data，value存放的就是长度
bool GetVarint32(Slice *input, uint32_t *value);
bool GetVarint64(Slice *input, uint32_t *value);

//将编码后的 string 中的长度信息去除，提出出原始 string。
bool GetLengthPrefixedSlice(Slice *input, Slice *result);

// Pointer-based variants of GetVarint...  These either store a value
// in *v and return a pointer just past the parsed value, or return
// nullptr on error.  These routines only look at bytes in the range
// [p..limit-1]
const char *GetVarint32Ptr(const char *p, const char *limit, uint32_t *v);
const char *GetVarint64Ptr(const char *p, const char *limit, uint64_t *v);

// 返回变长编码的长度
int VarintLength(uint64_t v);

// 编码
char *EncodeVarint32(char *dst, uint32_t value);
char *EncodeVarint64(char *dst, uint64_t value);

inline void EncodeFixed32(char *dst, uint32_t value) {

    uint8_t *const buffer = reinterpret_cast<uint8_t *>(dst);
    buffer[0] = static_cast<uint8_t>(value);
    buffer[1] = static_cast<uint8_t>(value >> 8);
    buffer[2] = static_cast<uint8_t>(value >> 16);
    buffer[3] = static_cast<uint8_t>(value >> 24);
    // 这样，buffer前四个元素组合起来就是int32，并且按小端对齐
}

inline void EncodeFixed64(char *dst, uint64_t value) {
    uint8_t *const buffer = reinterpret_cast<uint8_t *>(dst);
    buffer[0] = static_cast<uint8_t>(value);
    buffer[1] = static_cast<uint8_t>(value >> 8);
    buffer[2] = static_cast<uint8_t>(value >> 16);
    buffer[3] = static_cast<uint8_t>(value >> 24);
    buffer[4] = static_cast<uint8_t>(value >> 32);
    buffer[5] = static_cast<uint8_t>(value >> 40);
    buffer[6] = static_cast<uint8_t>(value >> 48);
    buffer[7] = static_cast<uint8_t>(value >> 56);
    // 这样，buffer前四个元素组合起来就是int64，并且按小端对齐
}

inline uint32_t DecodeFixed32(const char *ptr) {
    const uint8_t *const buffer = reinterpret_cast<const uint8_t *>(ptr);
    // 按位运算进行或
    uint32_t res = 0;
    res = (static_cast<uint32_t>(buffer[0])) |
          (static_cast<uint32_t>(buffer[1]) << 8) |
          (static_cast<uint32_t>(buffer[2]) << 16) |
          (static_cast<uint32_t>(buffer[3]) << 24);
    return res;
}

inline uint64_t DecodeFixed64(const char *ptr) {
    const uint8_t *const buffer = reinterpret_cast<const uint8_t *>(ptr);

    // Recent clang and gcc optimize this to a single mov / ldr instruction.
    return (static_cast<uint64_t>(buffer[0])) |
           (static_cast<uint64_t>(buffer[1]) << 8) |
           (static_cast<uint64_t>(buffer[2]) << 16) |
           (static_cast<uint64_t>(buffer[3]) << 24) |
           (static_cast<uint64_t>(buffer[4]) << 32) |
           (static_cast<uint64_t>(buffer[5]) << 40) |
           (static_cast<uint64_t>(buffer[6]) << 48) |
           (static_cast<uint64_t>(buffer[7]) << 56);
}
//解码，把解码过后的数字放在value里面，返回data开始的第一个字节
const char *GetVarint32PtrFallback(const char *p, const char *limit,
                                   uint32_t *value);

inline const char *GetVarint32Ptr(const char *p, const char *limit,
                                  uint32_t *value) {
    if (p < limit) {
        uint32_t res = *(reinterpret_cast<const uint8_t *>(p));
        if ((res & 128) == 0) {
            // 检查第八位是否为0
            *value = res;
            return p + 1;
        }
    }
        return GetVarint32PtrFallback(p, limit, value);

}

} // namespace leveldb

#endif